using Microsoft.Extensions.Logging;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Web;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services.Notification
{
    /// <summary>
    /// 华为云短信服务提供商
    /// 支持华为云消息与通知服务(SMN)
    /// </summary>
    public class HuaweiSmsProvider : ISmsProvider, IDisposable
    {
        public string Name => "华为云短信";

        public bool IsConfigured => !string.IsNullOrEmpty(_settings.AccessKeyId) &&
                                   !string.IsNullOrEmpty(_settings.SecretAccessKey) &&
                                   !string.IsNullOrEmpty(_settings.Region) &&
                                   !string.IsNullOrEmpty(_settings.ProjectId);

        private readonly HuaweiSmsSettings _settings;
        private readonly ILogger _logger;
        private readonly HttpClient _httpClient;
        private const string HUAWEI_SMS_ENDPOINT = "https://smsapi.{0}.myhuaweicloud.com";

        public HuaweiSmsProvider(HuaweiSmsSettings settings, ILogger logger)
        {
            _settings = settings ?? throw new ArgumentNullException(nameof(settings));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _httpClient = new HttpClient
            {
                Timeout = TimeSpan.FromSeconds(30)
            };
        }

        /// <summary>
        /// 发送普通短信
        /// </summary>
        public async Task<SmsSendResult> SendAsync(SmsMessage message)
        {
            if (!IsConfigured)
            {
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = "华为云短信提供商未正确配置",
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }

            try
            {
                var requestPayload = BuildSendSmsPayload(message);
                var jsonPayload = JsonSerializer.Serialize(requestPayload, new JsonSerializerOptions
                {
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
                });

                var requestUrl = string.Format(HUAWEI_SMS_ENDPOINT, _settings.Region) + "/sms/batchSendSms/v1";
                
                var startTime = DateTime.UtcNow;
                var response = await SendRequest(requestUrl, jsonPayload, "POST");
                var endTime = DateTime.UtcNow;

                if (response.Success)
                {
                    _logger.LogDebug(
                        "华为云短信发送成功 - 手机号: {Phone}, 耗时: {Duration}ms",
                        MaskPhoneNumber(message.PhoneNumber), (endTime - startTime).TotalMilliseconds);

                    return new SmsSendResult
                    {
                        Success = true,
                        MessageId = response.MessageId,
                        SentAt = endTime,
                        Provider = Name
                    };
                }
                else
                {
                    _logger.LogError(
                        "华为云短信发送失败 - 手机号: {Phone}, 错误: {Error}",
                        MaskPhoneNumber(message.PhoneNumber), response.ErrorMessage);

                    return new SmsSendResult
                    {
                        Success = false,
                        ErrorMessage = response.ErrorMessage,
                        SentAt = DateTime.UtcNow,
                        Provider = Name
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "华为云短信发送异常 - 手机号: {Phone}", MaskPhoneNumber(message.PhoneNumber));
                
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }
        }

        /// <summary>
        /// 使用模板发送短信
        /// </summary>
        public async Task<SmsSendResult> SendTemplateAsync(string templateId, Dictionary<string, string> templateParams, string phoneNumber, string? signName = null)
        {
            if (!IsConfigured)
            {
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = "华为云短信提供商未正确配置",
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }

            try
            {
                var requestPayload = BuildSendTemplatePayload(templateId, templateParams, phoneNumber, signName);
                var jsonPayload = JsonSerializer.Serialize(requestPayload, new JsonSerializerOptions
                {
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
                });

                var requestUrl = string.Format(HUAWEI_SMS_ENDPOINT, _settings.Region) + "/sms/batchSendSms/v1";
                
                var startTime = DateTime.UtcNow;
                var response = await SendRequest(requestUrl, jsonPayload, "POST");
                var endTime = DateTime.UtcNow;

                if (response.Success)
                {
                    _logger.LogDebug(
                        "华为云模板短信发送成功 - 手机号: {Phone}, 模板: {Template}, 耗时: {Duration}ms",
                        MaskPhoneNumber(phoneNumber), templateId, (endTime - startTime).TotalMilliseconds);

                    return new SmsSendResult
                    {
                        Success = true,
                        MessageId = response.MessageId,
                        SentAt = endTime,
                        Provider = Name
                    };
                }
                else
                {
                    _logger.LogError(
                        "华为云模板短信发送失败 - 手机号: {Phone}, 错误: {Error}",
                        MaskPhoneNumber(phoneNumber), response.ErrorMessage);

                    return new SmsSendResult
                    {
                        Success = false,
                        ErrorMessage = response.ErrorMessage,
                        SentAt = DateTime.UtcNow,
                        Provider = Name
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "华为云模板短信发送异常 - 手机号: {Phone}", MaskPhoneNumber(phoneNumber));
                
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }
        }

        /// <summary>
        /// 测试连接
        /// </summary>
        public async Task<bool> TestConnectionAsync()
        {
            if (!IsConfigured)
            {
                _logger.LogWarning("华为云短信提供商未配置，跳过连接测试");
                return false;
            }

            try
            {
                // 使用查询短信签名的API来测试连接
                var requestUrl = string.Format(HUAWEI_SMS_ENDPOINT, _settings.Region) + "/sms/signs/v1";
                var response = await SendRequest(requestUrl, "", "GET");

                if (response.Success || response.ErrorMessage?.Contains("InvalidParameter") == true || 
                    response.ErrorMessage?.Contains("ResourceNotFound") == true)
                {
                    // 如果成功或者是参数错误/资源未找到（说明API可访问），都认为连接正常
                    _logger.LogInformation("华为云短信服务连接测试成功");
                    return true;
                }
                else
                {
                    _logger.LogError("华为云短信服务连接测试失败 - 错误: {Error}", response.ErrorMessage);
                    return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "华为云短信服务连接测试异常");
                return false;
            }
        }

        /// <summary>
        /// 查询发送状态
        /// </summary>
        public async Task<SmsSendResult> QuerySendStatusAsync(string messageId)
        {
            if (!IsConfigured)
            {
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = "华为云短信提供商未正确配置",
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }

            try
            {
                var requestUrl = string.Format(HUAWEI_SMS_ENDPOINT, _settings.Region) + 
                    $"/sms/batchSendSms/v1/status?message_id={messageId}";
                
                var response = await SendRequest(requestUrl, "", "GET");

                return new SmsSendResult
                {
                    Success = response.Success,
                    MessageId = messageId,
                    ErrorMessage = response.Success ? null : response.ErrorMessage,
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "查询华为云短信发送状态异常 - 消息ID: {MessageId}", messageId);
                
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }
        }

        /// <summary>
        /// 构建发送普通短信的请求载荷
        /// </summary>
        private object BuildSendSmsPayload(SmsMessage message)
        {
            var phoneNumbers = new List<string> { FormatPhoneNumber(message.PhoneNumber) };

            return new
            {
                from = _settings.ChannelNumber,
                to = phoneNumbers,
                templateId = "SMS_001", // 纯文本短信模板ID
                templateParas = new[] { message.Content },
                signature = !string.IsNullOrEmpty(message.SignName) ? message.SignName : _settings.SignName
            };
        }

        /// <summary>
        /// 构建发送模板短信的请求载荷
        /// </summary>
        private object BuildSendTemplatePayload(string templateId, Dictionary<string, string> templateParams, string phoneNumber, string? signName)
        {
            var phoneNumbers = new List<string> { FormatPhoneNumber(phoneNumber) };
            
            // 将模板参数字典转换为数组
            var templateParamArray = templateParams?.Values.ToArray() ?? Array.Empty<string>();

            return new
            {
                from = _settings.ChannelNumber,
                to = phoneNumbers,
                templateId = templateId,
                templateParas = templateParamArray,
                signature = !string.IsNullOrEmpty(signName) ? signName : _settings.SignName
            };
        }

        /// <summary>
        /// 格式化手机号码
        /// </summary>
        private string FormatPhoneNumber(string phoneNumber)
        {
            if (string.IsNullOrEmpty(phoneNumber))
                return phoneNumber;

            // 移除所有非数字字符
            var cleanNumber = new string(phoneNumber.Where(char.IsDigit).ToArray());
            
            // 如果是中国手机号（11位），添加+86前缀
            if (cleanNumber.Length == 11 && cleanNumber.StartsWith("1"))
            {
                return "+86" + cleanNumber;
            }
            
            // 如果已经有+号，直接返回
            if (phoneNumber.StartsWith("+"))
            {
                return phoneNumber;
            }
            
            // 默认返回原号码
            return phoneNumber;
        }

        /// <summary>
        /// 发送请求
        /// </summary>
        private async Task<HuaweiSmsResponse> SendRequest(string endpoint, string payload, string method)
        {
            try
            {
                var uri = new Uri(endpoint);
                var headers = BuildAuthHeaders(uri, payload, method);
                
                var request = new HttpRequestMessage(new HttpMethod(method), endpoint);

                if (!string.IsNullOrEmpty(payload) && method == "POST")
                {
                    request.Content = new StringContent(payload, Encoding.UTF8, "application/json");
                }

                // 添加头信息
                foreach (var header in headers)
                {
                    if (header.Key == "Content-Type")
                        continue; // Content-Type已经在StringContent中设置
                    
                    request.Headers.TryAddWithoutValidation(header.Key, header.Value);
                }

                var response = await _httpClient.SendAsync(request);
                var responseContent = await response.Content.ReadAsStringAsync();

                if (response.IsSuccessStatusCode)
                {
                    try
                    {
                        var jsonDoc = JsonDocument.Parse(responseContent);
                        
                        if (jsonDoc.RootElement.TryGetProperty("result", out var resultElement))
                        {
                            if (resultElement.GetArrayLength() > 0)
                            {
                                var firstResult = resultElement[0];
                                var status = firstResult.TryGetProperty("status", out var statusElement)
                                    ? statusElement.GetString()
                                    : "000000";

                                if (status == "000000")
                                {
                                    var messageId = firstResult.TryGetProperty("msgId", out var msgIdElement)
                                        ? msgIdElement.GetString()
                                        : Guid.NewGuid().ToString();

                                    return new HuaweiSmsResponse
                                    {
                                        Success = true,
                                        MessageId = messageId
                                    };
                                }
                                else
                                {
                                    var description = firstResult.TryGetProperty("description", out var descElement)
                                        ? descElement.GetString()
                                        : "发送失败";

                                    return new HuaweiSmsResponse
                                    {
                                        Success = false,
                                        ErrorMessage = $"华为云错误 ({status}): {description}"
                                    };
                                }
                            }
                        }

                        // 对于GET请求（如连接测试），如果没有错误就认为成功
                        return new HuaweiSmsResponse
                        {
                            Success = true,
                            MessageId = Guid.NewGuid().ToString()
                        };
                    }
                    catch (JsonException)
                    {
                        // 如果响应不是JSON格式，但HTTP状态码是成功的，也认为成功
                        return new HuaweiSmsResponse
                        {
                            Success = true,
                            MessageId = Guid.NewGuid().ToString()
                        };
                    }
                }

                return new HuaweiSmsResponse
                {
                    Success = false,
                    ErrorMessage = $"HTTP错误: {response.StatusCode}, 响应: {responseContent}"
                };
            }
            catch (Exception ex)
            {
                return new HuaweiSmsResponse
                {
                    Success = false,
                    ErrorMessage = ex.Message
                };
            }
        }

        /// <summary>
        /// 构建认证头
        /// </summary>
        private Dictionary<string, string> BuildAuthHeaders(Uri uri, string payload, string method)
        {
            var timestamp = DateTime.UtcNow.ToString("yyyyMMddTHHmmssZ");
            var date = DateTime.UtcNow.ToString("yyyyMMdd");

            // 构建规范请求
            var canonicalUri = uri.AbsolutePath;
            var canonicalQueryString = string.IsNullOrEmpty(uri.Query) ? "" : uri.Query.Substring(1);
            var canonicalHeaders = $"host:{uri.Host}\nx-date:{timestamp}\n";
            var signedHeaders = "host;x-date";
            var hashedPayload = SHA256Hash(payload ?? "");

            var canonicalRequest = $"{method}\n{canonicalUri}\n{canonicalQueryString}\n{canonicalHeaders}\n{signedHeaders}\n{hashedPayload}";

            // 构建待签名字符串
            var algorithm = "AWS4-HMAC-SHA256";
            var credentialScope = $"{date}/cn-north-4/sms/aws4_request";
            var hashedCanonicalRequest = SHA256Hash(canonicalRequest);
            var stringToSign = $"{algorithm}\n{timestamp}\n{credentialScope}\n{hashedCanonicalRequest}";

            // 计算签名
            var kDate = HmacSHA256($"AWS4{_settings.SecretAccessKey}", date);
            var kRegion = HmacSHA256(kDate, "cn-north-4");
            var kService = HmacSHA256(kRegion, "sms");
            var kSigning = HmacSHA256(kService, "aws4_request");
            var signature = HmacSHA256(kSigning, stringToSign, true);

            // 构建Authorization头
            var authorization = $"{algorithm} Credential={_settings.AccessKeyId}/{credentialScope}, SignedHeaders={signedHeaders}, Signature={signature}";

            return new Dictionary<string, string>
            {
                ["Authorization"] = authorization,
                ["Host"] = uri.Host,
                ["X-Date"] = timestamp,
                ["X-Project-Id"] = _settings.ProjectId
            };
        }

        /// <summary>
        /// SHA256哈希
        /// </summary>
        private static string SHA256Hash(string input)
        {
            using var sha256 = SHA256.Create();
            var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));
            return Convert.ToHexString(hash).ToLowerInvariant();
        }

        /// <summary>
        /// HMAC-SHA256
        /// </summary>
        private static byte[] HmacSHA256(byte[] key, string data)
        {
            using var hmac = new HMACSHA256(key);
            return hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
        }

        /// <summary>
        /// HMAC-SHA256 with string key
        /// </summary>
        private static string HmacSHA256(string key, string data, bool hexResult = false)
        {
            using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
            var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
            return hexResult ? Convert.ToHexString(hash).ToLowerInvariant() : Convert.ToBase64String(hash);
        }

        /// <summary>
        /// 手机号码掩码处理
        /// </summary>
        private static string MaskPhoneNumber(string phoneNumber)
        {
            if (string.IsNullOrEmpty(phoneNumber) || phoneNumber.Length < 7)
                return phoneNumber;

            var start = phoneNumber.Substring(0, 3);
            var end = phoneNumber.Substring(phoneNumber.Length - 4);
            var mask = new string('*', phoneNumber.Length - 7);
            
            return start + mask + end;
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _httpClient?.Dispose();
        }
    }

    /// <summary>
    /// 华为云短信响应模型
    /// </summary>
    internal class HuaweiSmsResponse
    {
        public bool Success { get; set; }
        public string? MessageId { get; set; }
        public string? ErrorMessage { get; set; }
    }
}
